﻿using System;
using System.Threading;
using System.Threading.Tasks;
using AutoMapper;
using IdentityServer4.Configuration;
using K9Nano.Admin.Authentication;
using K9Nano.Admin.Data.Events;
using K9Nano.Admin.Weixin.OAuth;
using K9Nano.Configuration.Startup;
using K9Nano.Dependency;
using K9Nano.Events.Entity;
using K9Nano.Web;
using Microsoft.AspNetCore.Authentication;
using Microsoft.AspNetCore.Identity;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.DependencyInjection.Extensions;
using Microsoft.Extensions.Options;

namespace K9Nano.Admin
{
    public static class K9NanoAdminWebStartupExtensions
    {
        public static IK9NanoAppBuilder AddAdminWeb<TUser, TKey>(this IK9NanoAppBuilder builder,
            IConfiguration identityServerConfiguration,
            Action<IIdentityServerBuilder> configureIdentityServer)
            where TUser : IdentityUser<TKey>
            where TKey : IEquatable<TKey>
        {
            var thisAssembly = typeof(K9NanoAdminWebStartupExtensions).Assembly;

            builder.Services.Replace(ServiceDescriptor.Singleton<IEntityEventFilter, IdentityServerEntityEventFilter>());
            builder.Services.Replace(ServiceDescriptor.Singleton<IEntityCacheFilter, IdentityServerEntityCacheFilter>());
            builder.Services.RegisterConventionalAssembly(thisAssembly);
            builder.MvcApplicationPartAeAssemblies.Add(thisAssembly);

            var identityServerBuilder = builder.Services.AddIdentityServer(identityServerConfiguration)
                .AddAspNetIdentity<TUser>()
                .AddCustomTokenRequestValidator<K9TokenValidator>()
                .AddExtensionGrantValidator<WeiXinOpenGrantValidator>();

            configureIdentityServer?.Invoke(identityServerBuilder);

            builder.AddWebCore()
                .AddWeb();

            return builder;
        }

        public static AuthenticationBuilder AddWeixinMp(this AuthenticationBuilder builder,
            string authenticationScheme,
            string displayName,
            Action<WeixinOAuthOptions> configureOptions)
        {
            builder.Services.Configure<WeixinOAuthOptions>(configureOptions);

            builder.Services.AddHttpClient();
            
            return builder.AddRemoteScheme<WeixinOAuthOptions, WeixinOAuthHandler>(authenticationScheme, displayName, configureOptions);
        }
    }
}
